package de.hpi.bpmn2_0.validation;
import java.util.HashMap;
import java.util.List;
import de.hpi.bpmn2_0.model.BaseElement;
import de.hpi.bpmn2_0.model.Collaboration;
import de.hpi.bpmn2_0.model.Definitions;
import de.hpi.bpmn2_0.model.FlowElement;
import de.hpi.bpmn2_0.model.FlowNode;
import de.hpi.bpmn2_0.model.Process;
import de.hpi.bpmn2_0.model.NgsiEventDefinition;
import de.hpi.bpmn2_0.model.activity.Activity;
import de.hpi.bpmn2_0.model.activity.SubProcess;
import de.hpi.bpmn2_0.model.activity.type.ReceiveTask;
import de.hpi.bpmn2_0.model.bpmndi.BPMNEdge;
import de.hpi.bpmn2_0.model.bpmndi.BPMNShape;
import de.hpi.bpmn2_0.model.bpmndi.di.DiagramElement;
import de.hpi.bpmn2_0.model.choreography.Choreography;
import de.hpi.bpmn2_0.model.choreography.ChoreographyActivity;
import de.hpi.bpmn2_0.model.connector.DataInputAssociation;
import de.hpi.bpmn2_0.model.connector.DataOutputAssociation;
import de.hpi.bpmn2_0.model.connector.Edge;
import de.hpi.bpmn2_0.model.connector.MessageFlow;
import de.hpi.bpmn2_0.model.connector.SequenceFlow;
import de.hpi.bpmn2_0.model.data_object.DataInput;
import de.hpi.bpmn2_0.model.data_object.DataOutput;
import de.hpi.bpmn2_0.model.data_object.Message;
import de.hpi.bpmn2_0.model.event.BoundaryEvent;
import de.hpi.bpmn2_0.model.event.CompensateEventDefinition;
import de.hpi.bpmn2_0.model.event.ConditionalEventDefinition;
import de.hpi.bpmn2_0.model.event.EndEvent;
import de.hpi.bpmn2_0.model.event.Event;
import de.hpi.bpmn2_0.model.event.IntermediateCatchEvent;
import de.hpi.bpmn2_0.model.event.MessageEventDefinition;
import de.hpi.bpmn2_0.model.event.SignalEventDefinition;
import de.hpi.bpmn2_0.model.event.StartEvent;
import de.hpi.bpmn2_0.model.event.TimerEventDefinition;
import de.hpi.bpmn2_0.model.gateway.EventBasedGateway;
import de.hpi.bpmn2_0.model.gateway.Gateway;
import de.hpi.bpmn2_0.model.gateway.GatewayDirection;
import de.hpi.bpmn2_0.model.participant.Lane;
import de.hpi.bpmn2_0.model.participant.Participant;
import de.hpi.diagram.verification.AbstractSyntaxChecker;
/**
* Copyright (c) 2009 Philipp Giese
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
public class BPMN2SyntaxChecker extends AbstractSyntaxChecker {
protected static final String NO_SOURCE = "BPMN_NO_SOURCE";
protected static final String NO_TARGET = "BPMN_NO_TARGET";
protected static final String MESSAGE_FLOW_NOT_CONNECTED = "BPMN_MESSAGE_FLOW_NOT_CONNECTED";
protected static final String DIFFERENT_PROCESS = "BPMN_DIFFERENT_PROCESS";
protected static final String SAME_PROCESS = "BPMN_SAME_PROCESS";
protected static final String FLOWOBJECT_NOT_CONTAINED_IN_PROCESS = "BPMN_FLOWOBJECT_NOT_CONTAINED_IN_PROCESS";
protected static final String ENDEVENT_WITHOUT_INCOMING_CONTROL_FLOW = "BPMN_ENDEVENT_WITHOUT_INCOMING_CONTROL_FLOW";
protected static final String STARTEVENT_WITHOUT_OUTGOING_CONTROL_FLOW = "BPMN_STARTEVENT_WITHOUT_OUTGOING_CONTROL_FLOW";
// protected static final String
// INTERMEDIATEEVENT_WITHOUT_INCOMING_CONTROL_FLOW =
// "BPMN_INTERMEDIATEEVENT_WITHOUT_INCOMING_CONTROL_FLOW";
protected static final String STARTEVENT_WITH_INCOMING_CONTROL_FLOW = "BPMN_STARTEVENT_WITH_INCOMING_CONTROL_FLOW";
protected static final String ATTACHEDINTERMEDIATEEVENT_WITH_INCOMING_CONTROL_FLOW = "BPMN_ATTACHEDINTERMEDIATEEVENT_WITH_INCOMING_CONTROL_FLOW";
protected static final String ATTACHEDINTERMEDIATEEVENT_WITHOUT_OUTGOING_CONTROL_FLOW = "BPMN_ATTACHEDINTERMEDIATEEVENT_WITHOUT_OUTGOING_CONTROL_FLOW";
protected static final String ENDEVENT_WITH_OUTGOING_CONTROL_FLOW = "BPMN_ENDEVENT_WITH_OUTGOING_CONTROL_FLOW";
protected static final String EVENTBASEDGATEWAY_BADCONTINUATION = "BPMN_EVENTBASEDGATEWAY_BADCONTINUATION";
protected static final String NODE_NOT_ALLOWED = "BPMN_NODE_NOT_ALLOWED";
protected static final String MESSAGE_FLOW_NOT_ALLOWED = "BPMN_MESSAGE_FLOW_NOT_ALLOWED";
// BPMN 2.0 Specific
protected static final String DATA_INPUT_WITH_INCOMING_DATA_ASSOCIATION = "BPMN2_DATA_INPUT_WITH_INCOMING_DATA_ASSOCIATION";
protected static final String DATA_OUTPUT_WITH_OUTGOING_DATA_ASSOCIATION = "BPMN2_DATA_OUTPUT_WITH_OUTGOING_DATA_ASSOCIATION";
protected static final String EVENT_BASED_WITH_TOO_LESS_OUTGOING_SEQUENCE_FLOWS = "BPMN2_EVENT_BASED_WITH_TOO_LESS_OUTGOING_SEQUENCE_FLOWS";
protected static final String EVENT_BASED_TARGET_WITH_TOO_MANY_INCOMING_SEQUENCE_FLOWS = "BPMN2_EVENT_BASED_TARGET_WITH_TOO_MANY_INCOMING_SEQUENCE_FLOWS";
protected static final String EVENT_BASED_EVENT_TARGET_CONTRADICTION = "BPMN2_EVENT_BASED_EVENT_TARGET_CONTRADICTION";
protected static final String EVENT_BASED_WRONG_TRIGGER = "BPMN2_EVENT_BASED_WRONG_TRIGGER";
protected static final String EVENT_BASED_WRONG_CONDITION_EXPRESSION = "BPMN2_EVENT_BASED_WRONG_CONDITION_EXPRESSION";
protected static final String EVENT_BASED_NOT_INSTANTIATING = "BPMN2_EVENT_BASED_NOT_INSTANTIATING";
protected static final String EVENT_BASED_WITH_TOO_LESS_INCOMING_SEQUENCE_FLOWS = "BPMN2_EVENT_BASED_WITH_TOO_LESS_INCOMING_SEQUENCE_FLOWS";
protected static final String RECEIVE_TASK_WITH_ATTACHED_EVENT = "BPMN2_RECEIVE_TASK_WITH_ATTACHED_EVENT";
protected static final String GATEWAYDIRECTION_MIXED_FAILURE = "BPMN2_GATEWAYDIRECTION_MIXED_FAILURE";
protected static final String GATEWAYDIRECTION_CONVERGING_FAILURE = "BPMN2_GATEWAYDIRECTION_CONVERGING_FAILURE";
protected static final String GATEWAYDIRECTION_DIVERGING_FAILURE = "BPMN2_GATEWAYDIRECTION_DIVERGING_FAILURE";
protected static final String GATEWAY_WITH_NO_OUTGOING_SEQUENCE_FLOW = "BPMN2_GATEWAY_WITH_NO_OUTGOING_SEQUENCE_FLOW";
protected static final String GATEWAY_WITH_NO_INCOMING_SEQUENCE_FLOW = "BPMN2_GATEWAY_WITH_NO_INCOMING_SEQUENCE_FLOW";
protected static final String EVENT_SUBPROCESS_BAD_CONNECTION = "BPMN2_EVENT_SUBPROCESS_BAD_CONNECTION";
// CHOREOGRAPHY
protected static final String TOO_MANY_INITIATING_MESSAGES = "BPMN2_TOO_MANY_INITIATING_MESSAGES";
protected static final String TOO_MANY_INITIATING_PARTICIPANTS = "BPMN2_TOO_MANY_INITIATING_PARTICIPANTS";
protected static final String TOO_FEW_INITIATING_PARTICIPANTS = "BPMN2_TOO_FEW_INITIATING_PARTICIPANTS";
private Definitions defs;
// public HashSet<String> allowedNodes;
// public HashSet<String> forbiddenNodes;
public BPMN2SyntaxChecker(Definitions defs) {
this.defs = defs;
this.errors = new HashMap<String, String>();
// this.allowedNodes = new HashSet<String>();
// this.forbiddenNodes = new HashSet<String>();
}
// @Override
public boolean checkSyntax() {
errors.clear();
this.checkEdges();
this.checkNodes();
return errors.size() == 0;
}
private void checkEdges() {
for (Edge edge : this.defs.getEdges()) {
if (edge.getSourceRef() == null) {
this.addError(edge, NO_SOURCE);
} else if (edge.getTargetRef() == null) {
this.addError(edge, NO_TARGET);
} else {
if (edge instanceof MessageFlow) {
FlowElement source = edge.getSourceRef();
FlowElement target = edge.getTargetRef();
/*
* Not in same process or sub process
*/
if ((source.getProcess() != null
&& target.getProcess() != null && source
.getProcess() == target.getProcess())
|| (source.getSubProcess() != null
&& target.getSubProcess() != null && source
.getSubProcess() == target.getSubProcess())) {
this.addError(edge, SAME_PROCESS);
}
// if(edge.getSourceRef().getPool() ==
// edge.getTargetRef().getPool() &&
// edge.getSourceRef().getLane() !=
// edge.getTargetRef().getLane())
// this.addError(edge, MESSAGE_FLOW_NOT_ALLOWED);
if (edge.getSourceRef() instanceof Lane
|| edge.getTargetRef() instanceof Lane)
this.addError(edge, MESSAGE_FLOW_NOT_ALLOWED);
} else if (edge instanceof SequenceFlow) {
if (edge.getSourceRef().getProcess() != edge.getTargetRef()
.getProcess())
this.addError(edge, DIFFERENT_PROCESS);
}
}
}
}
private void checkNodes() {
for (BaseElement rootElement : this.defs.getRootElement()) {
/*
* Checking of Regular BPMN2.0 Diagrams
*/
if (rootElement instanceof Process) {
for (FlowElement flowElement : ((Process) rootElement)
.getFlowElement()) {
if (!(flowElement instanceof Edge)) {
this.checkNode(flowElement);
}
}
/*
* Checking of Choroegraphy Diagrams
*/
} else if (rootElement instanceof Choreography) {
for (FlowElement flowElement : ((Choreography) rootElement)
.getFlowElement()) {
if (!(flowElement instanceof Edge)) {
this.checkChoreographyNode(flowElement);
}
}
} else if(rootElement instanceof Collaboration) {
(new
BPMN2CollaborationChecker(this)).checkConversation((Collaboration)rootElement);
}
}
}
private void checkChoreographyNode(FlowElement flowElement) {
this.checkNode(flowElement);
if (flowElement instanceof ChoreographyActivity) {
Integer instantiationMessageCounter = this
.checkForInitiatingMessages((ChoreographyActivity) flowElement);
Integer instantiatingCounter = 0;
for (Participant participant : ((ChoreographyActivity) flowElement)
.getParticipantRef()) {
if (participant.isInitiating()) {
instantiatingCounter++;
if (instantiatingCounter > 1)
this.addError(participant,
TOO_MANY_INITIATING_PARTICIPANTS);
}
instantiationMessageCounter += this
.checkForInitiatingMessages(participant);
}
if (instantiatingCounter == 0)
this.addError(flowElement, TOO_FEW_INITIATING_PARTICIPANTS);
if (instantiationMessageCounter > 1)
this.addError(flowElement, TOO_MANY_INITIATING_MESSAGES);
}
}
private Integer checkForInitiatingMessages(FlowElement flowElement) {
Integer initiatingCounter = 0;
// Check outgoing edges
for (Edge outgoing : flowElement.getOutgoing())
if (outgoing.getTargetRef() instanceof Message)
if (((Message) outgoing.getTargetRef()).isInitiating())
initiatingCounter++;
// Check incoming edges
for (Edge incoming : flowElement.getIncoming())
if (incoming.getSourceRef() instanceof Message)
if (((Message) incoming.getSourceRef()).isInitiating())
initiatingCounter++;
return initiatingCounter;
}
private void checkNode(FlowElement node) {
// this.checkForAllowedAndForbiddenNodes(node);
if ((node instanceof Activity || node instanceof Event || node instanceof Gateway)
&& node.getProcess() == null) {
this.addError(node, FLOWOBJECT_NOT_CONTAINED_IN_PROCESS);
}
// Events
if (node instanceof EndEvent
&& !this.hasIncomingControlFlow((FlowNode) node))
this.addError(node, ENDEVENT_WITHOUT_INCOMING_CONTROL_FLOW);
if (node instanceof EndEvent
&& this.hasOutgoingControlFlow((FlowNode) node))
this.addError(node, ENDEVENT_WITH_OUTGOING_CONTROL_FLOW);
if (node instanceof StartEvent
&& this.hasIncomingControlFlow((FlowNode) node))
this.addError(node, STARTEVENT_WITH_INCOMING_CONTROL_FLOW);
if (node instanceof StartEvent
&& !this.hasOutgoingControlFlow((FlowNode) node))
this.addError(node, STARTEVENT_WITHOUT_OUTGOING_CONTROL_FLOW);
if (node instanceof BoundaryEvent)
this.checkBoundaryEvent((BoundaryEvent) node);
// Gateways
if (node instanceof Gateway) {
this.checkGateway((Gateway) node);
}
// Data Objects
if (node instanceof DataInput)
for (Edge edge : ((DataInput) node).getIncoming())
if (edge instanceof DataInputAssociation
|| edge instanceof DataOutputAssociation)
this.addError(node,
DATA_INPUT_WITH_INCOMING_DATA_ASSOCIATION);
if (node instanceof DataOutput)
for (Edge edge : ((DataOutput) node).getOutgoing())
if (edge instanceof DataInputAssociation
|| edge instanceof DataOutputAssociation)
this.addError(node,
DATA_OUTPUT_WITH_OUTGOING_DATA_ASSOCIATION);
// Subprocesses
if (node instanceof SubProcess)
this.checkSubProcess((SubProcess) node);
}
private void checkSubProcess(SubProcess node) {
/*
* this node is an event subprocess
*/
if (node.isTriggeredByEvent())
if (node.getIncomingSequenceFlows().size() > 0
|| node.getOutgoingSequenceFlows().size() > 0) {
// SPEC: P. 188
this.addError(node, EVENT_SUBPROCESS_BAD_CONNECTION);
}
}
private void checkGateway(Gateway node) {
/*
* Eventbased Gateways can instantiate processes, thus we have to handle
* them differently
*/
if (node instanceof EventBasedGateway)
this.checkEventBasedGateway((EventBasedGateway) node);
else
// SPEC: P. 298
this.checkCommomGateway(node);
}
private void checkCommomGateway(Gateway node) {
GatewayDirection direction = node.getGatewayDirection();
/*
* gateways must have a minimum of one outgoing sequence flow
*/
if (node.getOutgoingSequenceFlows().size() == 0) {
this.addError(node, GATEWAY_WITH_NO_OUTGOING_SEQUENCE_FLOW);
}
/*
* gateways must have a minimum of one incoming sequence flow
*/
else if (!(node instanceof EventBasedGateway)
&& node.getIncomingSequenceFlows().size() == 0) {
this.addError(node, GATEWAY_WITH_NO_INCOMING_SEQUENCE_FLOW);
}
/*
* must have both multiple incoming and outgoing sequence flows
*/
else if (direction.equals(GatewayDirection.MIXED)) {
if (node.getIncomingSequenceFlows().size() < 2
|| node.getOutgoingSequenceFlows().size() < 2) {
this.addError(node, GATEWAYDIRECTION_MIXED_FAILURE);
}
/*
* must have multiple incoming sequence flows and must NOT have
* multiple outgoing sequence flows
*/
} else if (direction.equals(GatewayDirection.CONVERGING)) {
if (!(node.getIncomingSequenceFlows().size() > 1 && node
.getOutgoingSequenceFlows().size() == 1)) {
this.addError(node, GATEWAYDIRECTION_CONVERGING_FAILURE);
}
/*
* must have multiple outgoing sequence flows and must NOT have
* multiple incoming sequence flows
*/
} else if (direction.equals(GatewayDirection.DIVERGING)) {
if (!(node.getIncomingSequenceFlows().size() == 1 && node
.getOutgoingSequenceFlows().size() > 1)) {
this.addError(node, GATEWAYDIRECTION_DIVERGING_FAILURE);
}
}
}
private void checkEventBasedGateway(EventBasedGateway node) {
List<SequenceFlow> outEdges = node.getOutgoingSequenceFlows();
boolean receiveTaskFlag = false;
boolean messageEventFlag = false;
if (outEdges.size() < 2)
// SPEC: P. 307
this.addError(node,
EVENT_BASED_WITH_TOO_LESS_OUTGOING_SEQUENCE_FLOWS);
if (node.isInstantiate() && !checkInstatiateCondition(node))
// SPEC: P. 309
this.addError(node, EVENT_BASED_NOT_INSTANTIATING);
if (!node.isInstantiate()
&& node.getIncomingSequenceFlows().size() == 0)
this.addError(node,
EVENT_BASED_WITH_TOO_LESS_INCOMING_SEQUENCE_FLOWS);
for (SequenceFlow edge : outEdges) {
/*
* outgoing sequence flows must NOT have a condition expression
*/
if (edge.getConditionExpression() != null)
// SPEC: P. 308
// TODO: Look out for the correct implementation
this.addError(edge, EVENT_BASED_WRONG_CONDITION_EXPRESSION);
if (!(edge.getTargetRef() instanceof IntermediateCatchEvent || edge
.getTargetRef() instanceof ReceiveTask)) {
this.addError(node, EVENTBASEDGATEWAY_BADCONTINUATION);
} else if (edge.getTargetRef() instanceof IntermediateCatchEvent) {
if (((IntermediateCatchEvent) edge.getTargetRef())
.getEventDefinitionOfType(MessageEventDefinition.class) != null)
messageEventFlag = true;
/* Check for correct Events triggers */
if (!checkTrigger((IntermediateCatchEvent) edge.getTargetRef()))
// SPEC: P. 308
this.addError(edge.getTargetRef(),
EVENT_BASED_WRONG_TRIGGER);
if (((IntermediateCatchEvent) edge.getTargetRef())
.getIncomingSequenceFlows().size() > 1)
// SPEC: P. 308
this
.addError(edge.getTargetRef(),
EVENT_BASED_TARGET_WITH_TOO_MANY_INCOMING_SEQUENCE_FLOWS);
} else if (edge.getTargetRef() instanceof ReceiveTask) {
receiveTaskFlag = true;
if (((ReceiveTask) edge.getTargetRef())
.getIncomingSequenceFlows().size() > 1)
// SPEC: P. 308
this
.addError(edge.getTargetRef(),
EVENT_BASED_TARGET_WITH_TOO_MANY_INCOMING_SEQUENCE_FLOWS);
if (((ReceiveTask) edge.getTargetRef()).getBoundaryEventRefs()
.size() != 0)
// SPEC: P. 308
this.addError(edge.getTargetRef(),
RECEIVE_TASK_WITH_ATTACHED_EVENT);
}
}
if (receiveTaskFlag && messageEventFlag)
// SPEC: P. 308
this.addError(node, EVENT_BASED_EVENT_TARGET_CONTRADICTION);
}
// TODO: Check if this Method and the invoked one are really necessary
// private void checkForAllowedAndForbiddenNodes(FlowElement node) {
// // Check for allowed and permitted nodes
// if(!checkForAllowedNode(node, allowedNodes, true) ||
// !checkForAllowedNode(node, forbiddenNodes, false)){
// System.out.println("error");
// addError(node, NODE_NOT_ALLOWED);
// }
// }
//
// private boolean checkForAllowedNode(FlowElement node, HashSet<String>
// classes, boolean allowed) {
// // If checking for allowed classes, empty classes means all are allowed
// if(allowed && classes.size() == 0)
// return true;
//
// boolean containedInClasses = false;
// String nodeClassName = node.getClass().getSimpleName();
//
// for(String clazz : classes){
// //TODO this doesn't checks for superclasses!!!
// // better would be "node instanceof Class.forName(clazz)"
// if(clazz.equals(nodeClassName)){
// containedInClasses = true;
// } else if(clazz.equals("MultipleInstanceActivity")){
// containedInClasses = (node instanceof Activity) &&
// ((Activity)node).isMultipleInstance();
// }
//
// if(containedInClasses) break;
// }
//
// return containedInClasses == allowed;
// }
private boolean checkInstatiateCondition(EventBasedGateway node) {
boolean hasStartEvent = false;
for (FlowElement flowElement : node.getProcess().getFlowElement()) {
if (flowElement instanceof StartEvent)
hasStartEvent = true;
}
/*
* if the process has no start events and the gateway has no incoming
* sequence flows it instantiates the process
*/
if (!hasStartEvent && node.getIncomingSequenceFlows().size() == 0)
return true;
/* OR */
/*
* the gateway has an incoming sequence flow but its source is a none
* start event
*/
if (node.getIncomingSequenceFlows().size() == 1) {
for (SequenceFlow sf : node.getIncomingSequenceFlows()) {
if (sf.getSourceRef() instanceof StartEvent) {
return true;
}
}
}
return false;
}
private boolean checkTrigger(IntermediateCatchEvent event) {
// TODO: Add support multiple
if (event.getEventDefinitionOfType(MessageEventDefinition.class) != null
|| event.getEventDefinitionOfType(TimerEventDefinition.class) != null
|| event.getEventDefinitionOfType(SignalEventDefinition.class) != null
|| event.getEventDefinitionOfType(NgsiEventDefinition.class) != null
|| event
.getEventDefinitionOfType(ConditionalEventDefinition.class) != null) {
return true;
}
return false;
}
private void checkBoundaryEvent(BoundaryEvent node) {
if (this.hasIncomingControlFlow(node))
this.addError(node,
ATTACHEDINTERMEDIATEEVENT_WITH_INCOMING_CONTROL_FLOW);
if (node.getOutgoingSequenceFlows().size() != 1
&& node
.getEventDefinitionOfType(CompensateEventDefinition.class) == null)
this.addError(node,
ATTACHEDINTERMEDIATEEVENT_WITHOUT_OUTGOING_CONTROL_FLOW);
}
private boolean hasIncomingControlFlow(FlowNode node) {
return node.getIncomingSequenceFlows().size() > 0;
}
private boolean hasOutgoingControlFlow(FlowNode node) {
return node.getOutgoingSequenceFlows().size() > 0;
}
/**
* Checks whether the {@link FlowElement} has a correlating diagram element.
*
* @param element
*
* @return
* true if diagram element exists
*/
private boolean hasCorelatingDiagramElement(FlowElement element) {
for(DiagramElement diaEl : defs.getFirstPlane().getDiagramElement()) {
if(diaEl instanceof BPMNShape
&& ((BPMNShape) diaEl).getBpmnElement().equals(element)) {
return true;
}
if(diaEl instanceof BPMNEdge
&& ((BPMNEdge) diaEl).getBpmnElement().equals(element)) {
return true;
}
}
return false;
}
protected void addError(FlowElement elem, String errorText) {
if(hasCorelatingDiagramElement(elem)) {
this.errors.put(elem.getId(), errorText);
}
}
}